#include "common.h"
#include "image.h"
#include "input.h"
#include "thread.h"

Input *in;
Output *out;
bool mode;
vector<Pixel> map;
sem_t em,em2, *wall;
int counter;
int NTHREADS  ;

/*sem_t em,log, escritores,leitores;
int logErro[LINHAS];
sem_t em2;//axo q tiramos*/

string convertInt(int number);

string convertInt(int number){
   stringstream ss;		//create a stringstream
   ss << number;		//add number to the stream
   return ss.str();		//return a string with the contents of the stream
}

//--funcao principal do programa
int main(int argc, char *argv[]) {
        
        //clock_t tInicial, tFinal;
	struct timeval tvi, tvf;
	struct timezone tzi, tzf;
	double delta;
 
	//Lendo o arquivo de entrada
	in = new Input("entrada.txt");
	out = new Output();
	out->create(in->N(),in->N());

	in->print();
	
	bool dynamic = true;	//Usar threads dinamicamente, se for false vai ser sempre sequencial
	int n = 1, m = 1;
	if(dynamic){
		n = in->N(); m = in->M();
	}
	
	double r = n/m;
	if((n%m))r+=1;
	NTHREADS = (int)(r*r);
	
	printf("Main->tamanho do quadrante: %d\n",(int)r);
	cout<<"Main->Numero de Threads: "<<NTHREADS<<endl;
	
	
	if(NTHREADS == 1){
		mode = SEQUENCIAL;
		cout<<"Main->modo sequencial"<<endl;
	}
	else{
		mode = MULTITHREAD;
		cout<<"Main->modo multiThread"<<endl;
		cout<<"Main->mapeando quadrantes"<<endl;
		for(register int y = 0;y < (int)r;++y){
			for(register int x = 0;x < (int)r;++x){
				map.push_back(Pixel(x,y));
			}
		}
		
		cout<<"Main->Inicializando semaphores"<<endl;
		counter = NTHREADS;
		wall = new sem_t[NTHREADS];
		sem_init(&em, 0, 1);
		sem_init(&em2, 0, 1);
		for(register int i = 0;i < NTHREADS;++i){
			sem_init(&wall[i], 0, 0);
		}
	}
	
	pthread_t *threads;
	threads = new pthread_t[NTHREADS];
//
	cout << "Comecando contagem de tempo (aproximado)" << endl;
	
	gettimeofday(&tvi, &tzi);
//	
	for(register int t=0; t<NTHREADS; t++) {
		printf("Main->Criando thread: %d\n",t);
		if (pthread_create(&threads[t], NULL, thread, (void *)t)) {
			printf("Main->ERRO: pthread_create()\n"); exit(-1);
		}
	}
	
	//--espera a thread terminar
	for(register int t=0; t<NTHREADS; t++) {if (pthread_join(threads[t], NULL)){printf("Main->ERRO: pthread_join() \n"); exit(-1);}}
	out->print();
	out->writeFile("saida.txt");
	printf("Main->terminou\n");

	for(int i = 0 ;i<1000000;i++){
	}
	
	gettimeofday(&tvf,&tzf);
	
	string modo;
	
	if(mode == SEQUENCIAL) {
		modo = "SEQUENCIAL";
	}
	else {
		modo = "CONCORRENTE";
	}
	
	delta = (double)(tvf.tv_usec - tvi.tv_usec);
	
	printf("\n\n%d\n\n\n%lf\n\n\n", delta, delta);

	
	double tempo = delta ;

		printf("\n\n%d\n\n\n%lf\n\n\n", (int)tempo, (float)tempo);
	
	cout << "A aplicacao " << modo << " levou " << tempo << " milissegundos." << endl;

	pthread_exit(NULL);
	
	delete in;
	delete out;
	delete[] wall;
	map.clear();
	return 0;
}
